import {
    _decorator,
    Camera,
    Component,
    EventMouse,
    EventTouch,
    Node,
    UITransform,
    v3,
    Vec2,
    Vec3
} from 'cc';
const { ccclass, property } = _decorator;

@ccclass('DropMove')
export class DropMove extends Component {
    
    @property({ type: Camera })
    camera: Camera | null = null; // 拖拽时使用的 2D 摄像机（默认为主摄像机）

    @property(Node)
    dragTarget: Node | null = null;

    private _dragging = false;
    private _offset = new Vec2();

    onLoad() {
        const target = this.dragTarget ?? this.node;

        target.on(Node.EventType.TOUCH_START, this.onMouseDown, this);
        target.on(Node.EventType.TOUCH_MOVE, this.onMouseMove, this);
        target.on(Node.EventType.TOUCH_END, this.onMouseUp, this);
        target.on(Node.EventType.TOUCH_CANCEL, this.onMouseUp, this); // 鼠标移出节点时也释放
    }

    onDestroy() {
        const target = this.dragTarget ?? this.node;
        target.off(Node.EventType.TOUCH_START, this.onMouseDown, this);
        target.off(Node.EventType.TOUCH_MOVE, this.onMouseMove, this);
        target.off(Node.EventType.TOUCH_END, this.onMouseUp, this);
        target.off(Node.EventType.TOUCH_CANCEL, this.onMouseUp, this);
    }

    private screenToWorld(screenPos: Vec3): Vec3 {
        const cam =
            this.camera ?? this.node.scene.getComponentInChildren(Camera);
        if (!cam) return screenPos;
        const out = new Vec3();
        cam.screenToWorld(screenPos, out);
        return out;
    }

    private onMouseDown(event: EventTouch) {
        const worldPos = this.screenToWorld(v2Tov3(event.getLocation()));
        const localPos = this.node
            .parent!.getComponent(UITransform)!
            .convertToNodeSpaceAR(worldPos);
        const currentPos = this.node.getPosition();
        this._offset.set(
            currentPos.x - localPos.x,
            currentPos.y - localPos.y,
        );
        this._dragging = true;
    }

    private onMouseMove(event: EventMouse) {
        if (!this._dragging) return;
        const worldPos = this.screenToWorld(v2Tov3(event.getLocation()));
        const localPos = this.node
            .parent!.getComponent(UITransform)!
            .convertToNodeSpaceAR(worldPos);
        this.node.setPosition(
            localPos.x + this._offset.x,
            localPos.y + this._offset.y,
        );
    }

    private onMouseUp(event: EventMouse) {
        this._dragging = false;
    }
    
}

function v2Tov3(v: Vec2) {
    return v3(v.x, v.y, 0);
}
